#pragma once 
#include "../Common/Util.hpp"
#include "../Common/Log.hpp"
#include <unistd.h>
#include <sys/wait.h>


class Compiler{
public:
    Compiler(){}
    ~Compiler(){}

    //获取一个文件的名字，然后需要进行一个编译
    //这里获取的是类似于：(hello).cpp  我们不要后缀
    static bool ComPile(const std::string name, const int& standard = 11){
        pid_t id = fork();
        if(id < 0){
            LOG(ERROR) << "内部错误: 创建子进程失败" << "\n";
            exit(1);  //先硬编码，后面改
        }
        else if(id == 0){
            //但是，我们今天希望，报错的信息打印到一个报错文件上，而不是stderr
            int newfd = open(PathUtil::Compile_err(name).c_str(), O_CREAT | O_WRONLY, 0664);
            if(newfd < 0){
                LOG(WARNING) << "内部错误: 没有创建出stderr文件" << "\n"; 
                return false;
            }
            //反之进行重定向
            dup2(newfd, 2);

            //这里应该是使用进程替换进行操作
            //1.首先要获取到真正要被编译的文件路径 和 要被生成的可执行文件
            std::string file = PathUtil::Src(name), exe = PathUtil::Exe(name);
            //2.使用进程替换，执行编译操作
            execlp("g++", "g++", "-o", exe.c_str(), file.c_str(), CppStandard[standard].c_str(), "-D", "COMPILER_ONLINE", nullptr);  //最后的nullptr一定要写！
            LOG(INFO) << "编译器g++调用失败, 可能是参数错误" << "\n";
            exit(2);   //直接让子进程退出
        }
        else{
            waitpid(id, nullptr, 0); //阻塞等待即可 因为子进程去做比编译
            //回收成功后，我们需要判断一下此次编译是否成功？
            bool ret =  FileUtil::IsFileExist(PathUtil::Exe(name));
            if(ret) LOG(INFO) << PathUtil::Src(name) << " 编译成功" << "\n";
            else LOG(ERROR) << PathUtil::Src(name) << " 编译失败, 没有形成 "<< PathUtil::Exe(name) << "\n";
            return ret;
        }
    }
private:
};